package com.aner.tester.scanner;

import com.aner.tester.exception.ScanningPackageErrorException;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description: the factory of package scanner
 *
 * @author aner
 * @version 1.0
 * @date 2020/10/19 21:14
 */
public class ScannerFactory {

    /**
     * scan class
     *
     * @param packageNames
     * @return the classes of required
     */
    public static Map<String, Class<?>> scan(String[] packageNames) {
        ClassScanner entityScanner = new ClassScanner.Builder().classPackages(packageNames).filterFlag(FilterFlag.NONE).build();
        return scanPackage(entityScanner);
    }

    /**
     * scan class
     *
     * @param packageNames
     * @param filterFlag
     * @return the classes of required
     */
    public static Map<String, Class<?>> scan(String[] packageNames, FilterFlag filterFlag) {
        ClassScanner entityScanner = new ClassScanner.Builder().classPackages(packageNames).filterFlag(filterFlag).build();
        return scanPackage(entityScanner);
    }

    /**
     *scan class
     *
     * @param annotationClass
     * @param packageNames
     * @param filterFlag
     * @return
     */
    public static Set<Class<?>> scan(Class<? extends Annotation> annotationClass,
                                             String[] packageNames, FilterFlag filterFlag) {
        return scan(Arrays.asList(annotationClass), packageNames, filterFlag);
    }

    /**
     * scan class
     *
     * @param packageNames
     * @return the classes of required
     */
    public static Set<Class<?>> scan(List<Class<? extends Annotation>> annotations,
                                     String[] packageNames, FilterFlag filterFlag) {
        List<TypeFilter> entityFilters = FilterBuilder.build(annotations);
        ClassScanner entityScanner = new ClassScanner.Builder().classPackages(packageNames).typeFilters(entityFilters).filterFlag(filterFlag).build();
        Map<String, Class<?>> entityMap = scanPackage(entityScanner);
        return entityMap.values().stream().collect(Collectors.toSet());
    }

    private static Map<String, Class<?>> scanPackage(ClassScanner entityScanner) {
        Map<String, Class<?>> entityMap = null;
        try {
            entityMap = entityScanner.scan();
        } catch (ClassNotFoundException | IOException e) {
            throw new ScanningPackageErrorException("Scanning package error: " + e.getMessage());
        }
        return entityMap;
    }

}
